#include "TechUser.h"
#include "TechUserDrv.h"
#include "Tech.h"
#include "../FacilityBaseLib/InstrumentData.h"
#include "Technique.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <PlatformStruct.h>
//////////////////////////////////////////////////////////////////////
//	CTechUser
custom_indicator_loader & GetTechUserDrv( );
//  static functions
UINT	custom_indicator::GetTechUserCount()
{
	//return GetTechUserDrv().GetTechUserCount();
	return 0;
}

std::string custom_indicator::GetTechUserName(int nTech)
{
	TECHUSER_INFO	info;
	memset( &info, 0, sizeof(info) );
	info.m_nStructSize	=	sizeof(info);
	if( GetTechUserDrv().GetTechUserInfo( nTech, &info ) )
		return string(info.m_szName);
	return ("");
}

std::string custom_indicator::GetTechUserShortName(int nTech)
{
	TECHUSER_INFO	info;
	memset( &info, 0, sizeof(info) );
	info.m_nStructSize	=	sizeof(info);
	if( GetTechUserDrv().GetTechUserInfo( nTech, &info ) )
		return string(info.m_szShortName);
	return ("");
}

custom_indicator::custom_indicator( )
{
	SetDefaultParameters( );
}

custom_indicator::custom_indicator( KdataContainer * pKData )
: TechnicalIndicator( pKData )
{
	SetDefaultParameters( );
}

custom_indicator::~custom_indicator()
{
	clear( );
}

bool custom_indicator::SetTechUserID( int nTechUserID )
{
	m_nTechUserID	=	nTechUserID;
	if( m_nTechUserID >= STT_USER_MIN
		&& m_nTechUserID-STT_USER_MIN<custom_indicator::GetTechUserCount() )
		return GetTechUserDrv().GetTechUserInfo( m_nTechUserID, &m_techuserinfo );
	return false;
}

UINT custom_indicator::GetTechUserID( )
{
	return m_nTechUserID;
}

void custom_indicator::SetInstrument( InstrumentData * pInstrument )
{
	m_pInstrument	=	pInstrument;
}

UINT custom_indicator::GetLineCount( )
{
	if( 1 == m_techuserinfo.m_nLineCount && m_techuserinfo.m_bAutoMA )
		return 2;
	return m_techuserinfo.m_nLineCount;
}

char* custom_indicator::GetLineName( int nLine )
{
	switch( nLine )
	{
	case 1:		return m_techuserinfo.m_aszLineName[0];
	case 2:
		if( 1 == m_techuserinfo.m_nLineCount && m_techuserinfo.m_bAutoMA )
			return "MA";
		return m_techuserinfo.m_aszLineName[1];
	case 3:		return m_techuserinfo.m_aszLineName[2];
	case 4:		return m_techuserinfo.m_aszLineName[3];
	case 5:		return m_techuserinfo.m_aszLineName[4];
	default:;
	}
	return "";
}

void custom_indicator::SetDefaultParameters( )
{
	m_nTechUserID	=	-1;
	memset( &m_techuserinfo, 0, sizeof(m_techuserinfo) );
}

void custom_indicator::attach( custom_indicator & src )
{
	m_nTechUserID	=	src.m_nTechUserID;
	memcpy( &m_techuserinfo, &(src.m_techuserinfo), sizeof(m_techuserinfo) );
}

bool custom_indicator::IsValidParameters( )
{
	return ( m_nTechUserID >= STT_USER_MIN
		&& m_nTechUserID-STT_USER_MIN<custom_indicator::GetTechUserCount() );
}

void custom_indicator::clear( )
{
	TechnicalIndicator::clear( );
}

int custom_indicator::signal( size_t nIndex, uint32_t * pnCode )
{
	if( pnCode )	*pnCode	=	ITSC_NOTHING;

	if( ( m_techuserinfo.m_nLineCount == 2 || (m_techuserinfo.m_nLineCount == 1 && m_techuserinfo.m_bAutoMA ) )
		&& ( ITS_NOTHING != m_techuserinfo.m_itsGoldenFork || ITS_NOTHING != m_techuserinfo.m_itsDeadFork ) )
	{
		int	nMaxDays	=	0;
		if( m_techuserinfo.m_nLineCount == 1 && m_techuserinfo.m_bAutoMA )
			nMaxDays	=	m_techuserinfo.m_nMADays;
		double	dLiminalLow = 0, dLiminalHigh = 0;
		if( !intensity_prepare( nIndex, pnCode, nMaxDays, ITS_GETMINMAXDAYRANGE, &dLiminalLow, &dLiminalHigh, 0.3, 0.7 ) )
			return ITS_NOTHING;

		if( nIndex <= 1 )
			return ITS_NOTHING;

		double	dValue1, dValue2;
		if( !calc( &dValue1, &dValue2, nIndex, false ) )
			return ITS_NOTHING;

		int	nSignal	=	GetForkSignal( nIndex, m_techuserinfo.m_itsGoldenFork, m_techuserinfo.m_itsDeadFork, pnCode );
		if( dValue1 < dLiminalLow && nSignal == ITS_BUY )
		{
			if( pnCode )	*pnCode	=	ITSC_GOLDENFORK;
			return ITS_BUY;
		}
		if( dValue1 > dLiminalHigh && nSignal == ITS_SELL )
		{
			if( pnCode )	*pnCode	=	ITSC_DEADFORK;
			return ITS_SELL;
		}
	}

	CALCULATE_INFO	info;
	memset( &info, 0, sizeof(info) );
	info.m_nStructSize	=	sizeof(info);
	info.m_pInstrument		=	m_pInstrument;
	info.m_pInstrumentInfo	=	&(m_pInstrument->GetInstrumentInfo());
	info.m_pKData		=	m_pKData;
	info.m_nIndex		=	nIndex;
	int nSignal = ITS_NOTHING;
	if( GetTechUserDrv().GetSignal( m_nTechUserID, &info ) )
	{
		//nSignal	=	info.m_nSignal;
		if( nSignal > ITS_NOTHING && pnCode )
			*pnCode	=	ITSC_LONG;
		if( nSignal < ITS_NOTHING && pnCode )
			*pnCode	=	ITSC_SHORT;
	}
	return nSignal;
}

//
int custom_indicator::intensity( size_t nIndex, uint32_t * pnCode, bool bTraceBack )
{
	return TechnicalIndicator::intensity( nIndex, pnCode, bTraceBack );
}

int custom_indicator::intensity_traceback( size_t nIndex, uint32_t * pnCode )
{
	return TechnicalIndicator::intensity_traceback( nIndex, pnCode );
}

bool custom_indicator::min_max_info(size_t nStart, size_t nEnd,
							  double *pdMin, double *pdMax )
{
	switch( m_techuserinfo.m_nLineCount )
	{
	case 1:
		return AfxGetMinMaxInfo1( nStart, nEnd, pdMin, pdMax, this );
	case 2:
		return AfxGetMinMaxInfo2( nStart, nEnd, pdMin, pdMax, this );
	case 3:
		return AfxGetMinMaxInfo3( nStart, nEnd, pdMin, pdMax, this );
	case 4:
		return AfxGetMinMaxInfo4( nStart, nEnd, pdMin, pdMax, this );
	case 5:
		return AfxGetMinMaxInfo5( nStart, nEnd, pdMin, pdMax, this );
	default:;
	}
	return false;
}

bool custom_indicator::calc( double * pValue, size_t nIndex, bool bUseLast )
{
	STT_ASSERT_CALCULATE1( m_pKData, nIndex );

	assert( 1 == m_techuserinfo.m_nLineCount );
	if( 1 != m_techuserinfo.m_nLineCount )
		return false;

	if( load_from_cache( nIndex, pValue ) )
		return true;

	CALCULATE_INFO	info;
	memset( &info, 0, sizeof(info) );
	info.m_nStructSize	=	sizeof(info);
	info.m_pInstrument		=	m_pInstrument;
	info.m_pInstrumentInfo	=	&(m_pInstrument->GetInstrumentInfo());
	info.m_pKData		=	m_pKData;
	info.m_nIndex		=	nIndex;
	info.m_bUseLast		=	bUseLast;
	if( bUseLast )
		info.m_dValue1	=	*pValue;
	if( !GetTechUserDrv().Calculate( m_nTechUserID, &info ) )
		return false;

	if( pValue )
		*pValue	=	info.m_dValue1;
	store_to_cache( nIndex, pValue );
	return true;
}

bool custom_indicator::calc( double * pValue1, double * pValue2, size_t nIndex, bool bUseLast )
{
	if( 1 == m_techuserinfo.m_nLineCount && m_techuserinfo.m_bAutoMA )
		return calc_ma( pValue1, pValue2, nIndex, bUseLast, m_techuserinfo.m_nMADays );

	STT_ASSERT_CALCULATE1( m_pKData, nIndex );

	assert( 2 == m_techuserinfo.m_nLineCount );
	if( 2 != m_techuserinfo.m_nLineCount )
		return false;

	if( load_from_cache( nIndex, pValue1, pValue2 ) )
		return true;

	CALCULATE_INFO	info;
	memset( &info, 0, sizeof(info) );
	info.m_nStructSize	=	sizeof(info);
	info.m_pInstrument		=	m_pInstrument;
	info.m_pInstrumentInfo	=	&(m_pInstrument->GetInstrumentInfo());
	info.m_pKData		=	m_pKData;
	info.m_nIndex		=	nIndex;
	info.m_bUseLast		=	bUseLast;
	if( bUseLast )
	{
		info.m_dValue1	=	*pValue1;
		info.m_dValue2	=	*pValue2;
	}
	if( !GetTechUserDrv().Calculate( m_nTechUserID, &info ) )
		return false;

	if( pValue1 )	*pValue1	=	info.m_dValue1;
	if( pValue2 )	*pValue2	=	info.m_dValue2;
	store_to_cache( nIndex, pValue1, pValue2 );
	return true;
}

bool custom_indicator::calc( double * pValue1, double * pValue2, double * pValue3, size_t nIndex, bool bUseLast )
{
	STT_ASSERT_CALCULATE1( m_pKData, nIndex );

	assert( 3 == m_techuserinfo.m_nLineCount );
	if( 3 != m_techuserinfo.m_nLineCount )
		return false;

	if( load_from_cache( nIndex, pValue1, pValue2, pValue3 ) )
		return true;

	CALCULATE_INFO	info;
	memset( &info, 0, sizeof(info) );
	info.m_nStructSize	=	sizeof(info);
	info.m_pInstrument		=	m_pInstrument;
	info.m_pInstrumentInfo	=	&(m_pInstrument->GetInstrumentInfo());
	info.m_pKData		=	m_pKData;
	info.m_nIndex		=	nIndex;
	info.m_bUseLast		=	bUseLast;
	if( bUseLast )
	{
		info.m_dValue1	=	*pValue1;
		info.m_dValue2	=	*pValue2;
		info.m_dValue3	=	*pValue3;
	}
	if( !GetTechUserDrv().Calculate( m_nTechUserID, &info ) )
		return false;

	if( pValue1 )	*pValue1	=	info.m_dValue1;
	if( pValue2 )	*pValue2	=	info.m_dValue2;
	if( pValue3 )	*pValue3	=	info.m_dValue3;
	store_to_cache( nIndex, pValue1, pValue2, pValue3 );
	return true;
}

bool custom_indicator::calc( double * pValue1, double * pValue2, double * pValue3, double *pValue4, size_t nIndex, bool bUseLast )
{
	STT_ASSERT_CALCULATE1( m_pKData, nIndex );

	assert( 4 == m_techuserinfo.m_nLineCount );
	if( 4 == m_techuserinfo.m_nLineCount )
		return false;

	if( load_from_cache( nIndex, pValue1, pValue2, pValue3, pValue4 ) )
		return true;

	CALCULATE_INFO	info;
	memset( &info, 0, sizeof(info) );
	info.m_nStructSize	=	sizeof(info);
	info.m_pInstrument		=	m_pInstrument;
	info.m_pInstrumentInfo	=	&(m_pInstrument->GetInstrumentInfo());
	info.m_pKData		=	m_pKData;
	info.m_nIndex		=	nIndex;
	info.m_bUseLast		=	bUseLast;
	if( bUseLast )
	{
		info.m_dValue1	=	*pValue1;
		info.m_dValue2	=	*pValue2;
		info.m_dValue3	=	*pValue3;
		info.m_dValue4	=	*pValue4;
	}
	if( !GetTechUserDrv().Calculate( m_nTechUserID, &info ) )
		return false;

	if( pValue1 )	*pValue1	=	info.m_dValue1;
	if( pValue2 )	*pValue2	=	info.m_dValue2;
	if( pValue3 )	*pValue3	=	info.m_dValue3;
	if( pValue4 )	*pValue4	=	info.m_dValue4;
	store_to_cache( nIndex, pValue1, pValue2, pValue3, pValue4 );
	return true;
}

bool custom_indicator::calc( double * pValue1, double * pValue2, double * pValue3, double *pValue4, double *pValue5, size_t nIndex, bool bUseLast )
{
	STT_ASSERT_CALCULATE1( m_pKData, nIndex );

	assert( 5 == m_techuserinfo.m_nLineCount );
	if( 5 == m_techuserinfo.m_nLineCount )
		return false;

	if( load_from_cache( nIndex, pValue1, pValue2, pValue3, pValue4, pValue5 ) )
		return true;

	CALCULATE_INFO	info;
	memset( &info, 0, sizeof(info) );
	info.m_nStructSize	=	sizeof(info);
	info.m_pInstrument		=	m_pInstrument;
	info.m_pInstrumentInfo	=	&(m_pInstrument->GetInstrumentInfo());
	info.m_pKData		=	m_pKData;
	info.m_nIndex		=	nIndex;
	info.m_bUseLast		=	bUseLast;
	if( bUseLast )
	{
		info.m_dValue1	=	*pValue1;
		info.m_dValue2	=	*pValue2;
		info.m_dValue3	=	*pValue3;
		info.m_dValue4	=	*pValue4;
		info.m_dValue5	=	*pValue5;
	}
	if( !GetTechUserDrv().Calculate( m_nTechUserID, &info ) )
		return false;

	if( pValue1 )	*pValue1	=	info.m_dValue1;
	if( pValue2 )	*pValue2	=	info.m_dValue2;
	if( pValue3 )	*pValue3	=	info.m_dValue3;
	if( pValue4 )	*pValue4	=	info.m_dValue4;
	if( pValue5 )	*pValue5	=	info.m_dValue5;
	store_to_cache( nIndex, pValue1, pValue2, pValue3, pValue4, pValue5 );
	return true;
}
